package org.lgy.sso_server.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.lgy.sso_comment.constant.AuthConst;
import org.lgy.sso_comment.storage.SessionStorage;
import org.lgy.sso_comment.util.EncryptUtil;
import org.lgy.sso_server.entity.User;
import org.lgy.sso_server.manager.SessionManager;
import org.lgy.sso_server.service.UserService;
import org.lgy.sso_server.storage.ClientStorage;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 登录和注销控制器
 */
@Slf4j
@Controller
public class LoginController {

	@Resource
	private UserService userService;

	@Resource
	private SessionManager sessionManager;

	@RequestMapping("/")
	public String index(HttpServletRequest request, Model model) {
		model.addAttribute(AuthConst.CLIENT_URL, request.getParameter(AuthConst.CLIENT_URL));
		return "login/index";
	}

	@RequestMapping("/success")
	public String success() {
		return "success";
	}
	
	/**
	 * 登录
	 */
	@RequestMapping("/login")
	public String login(HttpServletRequest request, User input, Model model) {
		// 验证用户
		User user = userService.getOne(new QueryWrapper<>(input));
		if (user == null) {
			model.addAttribute("error", "username or password is wrong.");
			return "redirect:/";
		}

		// 授权
		String token = IdUtil.fastSimpleUUID();
		request.getSession().setAttribute(AuthConst.IS_LOGIN, true);
		request.getSession().setAttribute(AuthConst.TOKEN, token);
		
		// 存储，用于注销
		SessionStorage.INSTANCE.set(token, request.getSession());

		// 子系统跳转过来的登录请求，授权、存储后，跳转回去
		String clientUrl = input.getClientUrl();
		if (clientUrl != null && !"".equals(clientUrl)) {
			// 存储，用于注销
			ClientStorage.INSTANCE.set(token, clientUrl);
			return "redirect:" + clientUrl + "?" + AuthConst.TOKEN + "=" + token;
		}

		return "success";
	}

	/**
	 * 注销
	 */
	@RequestMapping("/logout")
	public String logout(HttpServletRequest request) {
		HttpSession session = request.getSession();
		String token = request.getParameter(AuthConst.LOGOUT_REQUEST);
		
		// token存在于请求中，表示从客户端发起的注销；token存在于会话中，表示从认证中心发起的注销
		if (StrUtil.isNotBlank(token)) {
			session = SessionStorage.INSTANCE.get(token);
			SessionStorage.INSTANCE.remove(token);
		} else {
			token = (String) session.getAttribute(AuthConst.TOKEN);
		}
		
		if (session != null) {
			session.invalidate();
		}
		
		// 注销子系统
		sessionManager.logout(token);
		log.info("ssoServer 已退出登录");
		
		return "redirect:/";
	}

	/**
	 * 验证token是否有效
	 */
	@RequestMapping("/tokenCheck")
	public void tokenCheck(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String token = request.getParameter(AuthConst.TOKEN);
		String clientUrl = request.getParameter(AuthConst.CLIENT_URL);
		HttpSession session = SessionStorage.INSTANCE.get(token);
		if (session != null) {
			response.sendRedirect(clientUrl + "?" + AuthConst.TOKEN_CHECK_RESULT + "=" + EncryptUtil.aesEncrypt("pass") + "&tokenCheck=check" + "&" + AuthConst.LOGIN_TOKEN + "=" + token);
		} else {
			response.sendRedirect(clientUrl + "?" + AuthConst.TOKEN_CHECK_RESULT + "=" + EncryptUtil.aesEncrypt("fail") + "&tokenCheck=check" + "&" + AuthConst.LOGIN_TOKEN + "=" + token);
		}
	}
}